#include "LineCryptoer.h"
#include "Poco\StringTokenizer.h"
#include "Poco\Util\LayeredConfiguration.h"
#include "Poco\Util\Application.h"
#include <vector>
#include <sstream>
#include <Poco\Logger.h>
using Poco::StringTokenizer;
using Poco::Util::Application;

LineCryptoer::LineCryptoer()
{
}


LineCryptoer::~LineCryptoer()
{
}
std::string LineCryptoer::encodeContents(std::string contents, std::string file_base, std::string file_ext)
{
	Application& app = Application::instance();
	std::string fh = app.config().getString(file_ext + ".line_fix_mode.file_header", "");
	if (!fh.empty())
		fh += "\r\n";
	std::string ft = app.config().getString(file_ext + ".line_fix_mode.file_tailer", "");
	std::string lh = app.config().getString(file_ext + ".line_fix_mode.line_header", "");
	std::string lt = app.config().getString(file_ext + ".line_fix_mode.line_tailer", "");
	int line_size = app.config().getInt("line_buffer_size", 2);
	std::string out = fh;
	std::string tmp;
	std::vector<std::string> lines;
	StringTokenizer st(contents, "\n");
	size_t count = st.count();
	for (int i = 0; i < count; i+=line_size) {
		tmp = "";
		for (int j = 0; j < line_size; j++)
		{
			if (i + j < count) {
				tmp += st[i + j];
				if (i + j != count - 1)
					tmp += '\n';
			}else{
				break;
			}
		}
		std::stringstream ss;
		ss << i;
		std::string plh = replaceAll(lh, "%LINE_NUMBER%", ss.str());
		std::string plt = replaceAll(lt, "%LINE_NUMBER%", ss.str());
		out += plh + pCipher->encryptString(tmp, Cipher::ENC_BASE64_NO_LF) + plt;
		if(i+line_size<count)
			out+="\r\n";
	}
	out += ft;
	return out;
}

std::string LineCryptoer::decodeContents(std::string contents, std::string file_base, std::string file_ext)
{
	Application& app = Application::instance();
	std::string fh = app.config().getString(file_ext + ".line_fix_mode.file_header", "");
	if (!fh.empty())
		fh += "\r\n";
	std::string ft = app.config().getString(file_ext + ".line_fix_mode.file_tailer", "");
	std::string lh = app.config().getString(file_ext + ".line_fix_mode.line_header", "");
	std::string lt = app.config().getString(file_ext + ".line_fix_mode.line_tailer", "");
	int line_size = app.config().getInt("line_buffer_size", 2);
	std::string out;
	size_t fhlen = fh.length();
	size_t ftlen = ft.length();
	std::string sbuf = contents.substr(fhlen, contents.length() - fhlen - ftlen);
	StringTokenizer st(sbuf, "\n");
	StringTokenizer::Iterator it = st.begin();
	int i = 0;
	while (it != st.end()) {
		std::stringstream ss;
		ss << i++;
		std::string plh = replaceAll(lh, "%LINE_NUMBER%", ss.str());
		std::string plt = replaceAll(lt, "%LINE_NUMBER%", ss.str());
		size_t lhlen = plh.length();
		size_t ltlen = plt.length();
		std::string cur = *it++;
		std::string curbuf = cur.substr(lhlen, cur.length() - lhlen - ltlen);
		out += pCipher->decryptString(curbuf, Cipher::ENC_BASE64_NO_LF);
	}
	return out;
}

void LineCryptoer::showInfo()
{
	Application& app = Application::instance();
	app.logger().information("Using line mode.\n");
}
